const { Op } = require("sequelize")

const {
    getRoleInfo,
    createRole,
    modifyByRoleCode,
    deleteByRoleCode,
    getRoleList
} = require('../service/role.service')
const { getMenuById, getAllMenu } = require('../service/menu.service')
const { modifyUserBindRole } = require('../service/user.service')
const {
    roleAddError,
    roleModifyError
} = require('../constant/err.type')

// 递归处理数组
function tree (parentList, childList) {
    for (const item of parentList) {
        item.children = []
        for (const i in childList) {
            const v = childList[i]
            if (item.id == v.parentId) {
                item.children.push(v)
                // 这一步递归 如果没有下面三行代码 只能找到第一级对应的children第二级目录
                let c = JSON.parse(JSON.stringify(childList)) // 简单深拷贝一下
                // 能走到这儿，说明这个娃 已经找到父亲了 不需要在遍历了 所以删了 你要是非的不删也可以
                // 注意这里是具体根据业务的，如果不同父目录下面可能有相同的子目录，这里就不能删除了
                c.splice(i, 1)
                // 这里需要把当前儿子 加上[]转为数组因为tree接受的是父，子数组
                tree([v], c)
            }
        }
    }
    return parentList
}

class roleController {
    /**
     * 通过用户权限生成菜单
     */
    async getMenuListByRole (ctx, next) {
        const { roleCode } = ctx.query
        // 获取该角色的菜单权限
        const roleRes = await getRoleInfo({ role_code: roleCode })
        const { menu } = roleRes[0].dataValues
        let menuIdList = menu.split(',')
        let menuItemList = []
        for (const i in menuIdList) {
            const menuItem = await getMenuById(menuIdList[i])
            menuItemList.push(menuItem)
        }
        // 将数组处理为前端菜单需要的样式
        menuItemList.forEach(item => {
            item.parentId = item.parent_id
            delete item.parent_id
            if (item.title && item.icon) {
                const tempObj = {}
                tempObj.title = item.title
                tempObj.icon = item.icon
                item.meta = tempObj
            }
        })
        menuItemList.sort((a, b) => { return a.id - b.id })
        // 将菜单列表整理成树形格式
        const parentList = menuItemList.filter(item => item.parentId == 0)
        const childList = menuItemList.filter(item => item.parentId != 0)

        // 递归处理数组
        const menuList = tree(parentList, childList)

        ctx.status = 200
        ctx.body = {
            hasOk: true,
            code: 20000,
            message: '菜单获取成功',
            data: {
                menuList
            }
        }
    }

    /**
     * 获取所有菜单
     */
    async getAllMenuList (ctx, next) {
        const res = await getAllMenu()

        let menuItemList = []
        // 将数组处理为前端菜单需要的样式
        res.forEach(item => {
            let menuItem = {}
            menuItem.parentId = item.parent_id
            menuItem.name = item.name
            menuItem.title = item.title
            menuItem.id = item.id
            menuItem.path = item.path
            if (item.title && item.icon) {
                const tempObj = {}
                tempObj.title = item.title
                tempObj.icon = item.icon
                menuItem.meta = tempObj
            }
            menuItemList.push(menuItem)
        })
        menuItemList.sort((a, b) => { return a.id - b.id })
        // 将菜单列表整理成树形格式
        const parentList = menuItemList.filter(item => item.parentId == 0)
        const childList = menuItemList.filter(item => item.parentId != 0)

        // 递归处理数组
        const menuList = tree(parentList, childList)

        ctx.status = 200
        ctx.body = {
            hasOk: true,
            code: 20000,
            message: '菜单获取成功',
            data: {
                menuList
            }
        }
    }


    /**
     * 新增角色
     */
    async addRole (ctx, next) {
        const { roleName, menu, roleCode, roleDesc } = ctx.request.body
        // 写入数据
        try {
            const res = await createRole({ role_name: roleName, menu, role_code: roleCode, role_desc: roleDesc })
            if (res.errorFlag) {
                console.error('新增失败，数据库新增数据错误', res.message)
                ctx.status = 500
            } else {
                ctx.status = 200
                ctx.body = {
                    hasOk: true,
                    code: 20000,
                    message: '成功新增角色',
                    data: {
                        id: res.id,
                        roleName: res.role_name,
                        roleCode: res.role_code
                    }
                }
            }
        } catch (error) {
            console.error('角色新增失败', error)
            ctx.app.emit('error', roleAddError, ctx)
            return
        }
    }

    /**
     * 修改角色信息
     */
    async modifyRoleInfo (ctx, next) {
        const { roleCode, roleName, roleDesc } = ctx.request.body
        const roleModifyInfo = { role_name: roleName, role_desc: roleDesc }
        try {
            const res = await modifyByRoleCode(roleModifyInfo, roleCode)
            if (res.errorFlag) {
                console.error('修改失败，数据库错误', res.message)
                ctx.status = 500
            } else {
                ctx.status = 200
                ctx.body = {
                    hasOk: true,
                    code: 20000,
                    message: '角色信息修改成功',
                    data: ''
                }
            }
        } catch (error) {
            console.error('数据修改失败', error)
            ctx.app.emit('error', roleModifyError, ctx)
            return
        }
    }

    /**
     * 修改角色菜单权限
     */
    async modifyMenu (ctx, next) {
        const { roleCode, menu } = ctx.request.body
        try {
            const res = await modifyByRoleCode({ menu }, roleCode)
            if (res.errorFlag) {
                console.error('修改失败，数据库错误', res.message)
                ctx.status = 500
            } else {
                ctx.status = 200
                ctx.body = {
                    hasOk: true,
                    code: 20000,
                    message: '菜单权限修改成功',
                    data: ''
                }
            }
        } catch (error) {
            console.error('数据修改失败', error)
            ctx.app.emit('error', roleModifyError, ctx)
            return
        }
    }


    /**
     * 删除角色
     */
    async deleteRole (ctx, next) {
        const { roleCode, newRoleCode } = ctx.request.body
        const res = await modifyUserBindRole(roleCode, newRoleCode)
        if (res.errorFlag) {
            console.error('角色换绑失败，数据库错误', res.message)
            ctx.status = 500
            return
        }
        try {
            const res = await deleteByRoleCode(roleCode)
            if (res.errorFlag) {
                console.error('删除失败，数据库错误', res.message)
                ctx.status = 500
            } else {
                ctx.status = 200
                ctx.body = {
                    hasOk: true,
                    code: 20000,
                    message: '删除成功',
                    data: { roleCode }
                }
            }
        } catch (error) {
            console.error('用户删除失败', error)
            ctx.app.emit('error', roleDeleteError, ctx)
            return
        }
    }

    /**
     * 获取角色列表
     */
    async getRoleList (ctx, next) {
        try {
            const { roleName: role_name, roleCode: role_code } = ctx.query
            let { limit, offect } = ctx.query
            offect = limit * offect - limit
            const whereOpt = {}

            // 短路运算 值存在就拷贝进whereOpt
            // [Op.substring] 为模糊查询
            role_name && Object.assign(whereOpt, { role_name: { [Op.substring]: role_name } })
            role_code && Object.assign(whereOpt, { role_code: { [Op.substring]: role_code } })

            const { count, rows, errorFlag, message } = await getRoleList(whereOpt, limit, offect)
            let resList = []
            rows.forEach(item => {
                let tempObj = {}
                tempObj.id = item.id
                tempObj.roleName = item.role_name
                tempObj.roleCode = item.role_code
                tempObj.menu = item.menu
                tempObj.roleDesc = item.role_desc
                tempObj.createdAt = item.createdAt
                tempObj.updatedAt = item.updatedAt
                resList.push(tempObj)
            })
            if (errorFlag) {
                console.error('获取失败，数据库错误', message)
                ctx.status = 500
            } else {
                ctx.status = 200
                ctx.body = {
                    hasOk: true,
                    code: 20000,
                    data: {
                        resList,
                        count
                    }
                }
            }
        } catch (error) {
            console.log(error)
        }

    }
}

module.exports = new roleController()